package com.sqx.modules.app.controller.app.apple;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.braintreegateway.BraintreeGateway;
import com.braintreegateway.Environment;
import com.braintreegateway.Transaction;
import com.braintreegateway.TransactionRequest;
import com.sqx.common.utils.RedisUtils;
import com.sqx.common.utils.Result;
import com.sqx.modules.app.Constant.OrdersConstants;
import com.sqx.modules.app.annotation.Login;
import com.sqx.modules.app.config.BraintreeConfig;
import com.sqx.modules.app.entity.UserEntity;
import com.sqx.modules.app.entity.UserMoney;
import com.sqx.modules.app.entity.UserMoneyDetails;
import com.sqx.modules.app.entity.UserVip;
import com.sqx.modules.app.entity.dto.ApplePayDto;
import com.sqx.modules.app.entity.dto.IosNotificationRequest;
import com.sqx.modules.app.entity.dto.IospayDto;
import com.sqx.modules.app.service.UserMoneyDetailsService;
import com.sqx.modules.app.service.UserMoneyService;
import com.sqx.modules.app.service.UserService;
import com.sqx.modules.app.service.UserVipService;
import com.sqx.modules.course.entity.CourseUser;
import com.sqx.modules.course.service.CourseUserService;
import com.sqx.modules.invite.service.InviteService;
import com.sqx.modules.orders.entity.Orders;
import com.sqx.modules.orders.service.OrdersService;
import com.sqx.modules.pay.dao.UserDramaDetailsDao;
import com.sqx.modules.pay.dao.UserDramaPointDao;
import com.sqx.modules.pay.entity.PayClassify;
import com.sqx.modules.pay.entity.PayDetails;
import com.sqx.modules.pay.entity.UserDramaDetails;
import com.sqx.modules.pay.entity.UserDramaPoint;
import com.sqx.modules.pay.service.PayClassifyService;
import com.sqx.modules.utils.AliPayOrderUtil;
import com.sqx.modules.utils.IosVerifyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.io.FileInputStream;
import java.math.BigDecimal;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/app/applePay")
public class ApplePayController {

    @Autowired
    private OrdersService ordersService;
    @Autowired
    private CourseUserService courseUserService;
    @Autowired
    private UserVipService userVipService;
    @Autowired
    private UserMoneyService userMoneyService;
    @Autowired
    private UserMoneyDetailsService userMoneyDetailsService;
    @Autowired
    private UserService userService;
    @Autowired
    private InviteService inviteService;
    @Autowired
    private PayClassifyService payClassifyService;
    @Autowired
    private UserDramaPointDao userDramaPointDao;
    @Autowired
    private UserDramaDetailsDao userDramaDetailsDao;



    /**
     * 苹果内购校验
     * @return
     */
    @PostMapping("/iospay")
    @Transactional
    public Result iospay(@RequestBody IospayDto iospayDto) {
        log.info("苹果内购校验开始，交易ID：" + iospayDto.getTransactionId() + " base64校验体：" + iospayDto.getPayload());
        //线上环境验证
        String verifyResult = IosVerifyUtil.buyAppVerify(iospayDto.getPayload(), 1);
        if (verifyResult == null) {
            return Result.error("苹果验证失败，返回数据为空");
        } else {
            log.info("线上，苹果平台返回JSON:" + verifyResult);
            JSONObject appleReturn = JSONObject.parseObject(verifyResult);
            String states = appleReturn.getString("status");
            //无数据则沙箱环境验证

            //0 正常
            //21000 App Store不能读取你提供的JSON对象
            //21002 receipt-data域的数据有问题
            //21003 receipt无法通过验证
            //21004 提供的shared secret不匹配你账号中的shared secret
            //21005 receipt服务器当前不可用
            //21006 receipt合法，但是订阅已过期。服务器接收到这个状态码时，receipt数据仍然会解码并一起发送
            //21007 receipt是Sandbox receipt，但却发送至生产系统的验证服务
            //21008 receipt是生产receipt，但却发送至Sandbox环境的验证服务

            if ("21007".equals(states)) {
                verifyResult = IosVerifyUtil.buyAppVerify(iospayDto.getPayload(), 0);
                log.info("沙盒环境，苹果平台返回JSON:" + verifyResult);
                appleReturn = JSONObject.parseObject(verifyResult);
                states = appleReturn.getString("status");
            }
            log.info("苹果平台返回值：appleReturn" + appleReturn);
            // 前端所提供的收据是有效的    验证成功
            if (states.equals("0")) {
                String receipt = appleReturn.getString("receipt");
                JSONObject returnJson = JSONObject.parseObject(receipt);
                String inApp = returnJson.getString("in_app");
                System.out.println("============>"+inApp);
                List<HashMap> inApps = JSONObject.parseArray(inApp, HashMap.class);
                if (!CollectionUtils.isEmpty(inApps)) {//IOS7之后
                    ArrayList<String> transactionIds = new ArrayList<String>();
                    String productId = "";
                    for (HashMap app : inApps) {
                        transactionIds.add((String) app.get("transaction_id"));
                        if (app.get("transaction_id").toString().equals(iospayDto.getTransactionId())) {
                            productId = app.get("product_id").toString();
                        }
                    }
                    //交易列表包含当前交易，则认为交易成功
                    if (transactionIds.contains(iospayDto.getTransactionId())) {
                        //处理业务逻辑
                        Orders orders = ordersService.selectOrderById(iospayDto.getOrderId());
                        if (ObjectUtils.isEmpty(orders))return Result.error("该订单不存在");
                        orders.setStatus(1);
                        orders.setPayWay(OrdersConstants.ORDERS_PAY_WAY_APPLE);
                        orders.setTransactionId(Long.valueOf(iospayDto.getTransactionId()));
                        orders.setPurchaseId(productId);
                        ordersService.updateById(orders);
                        UserEntity user = userService.selectUserById(orders.getUserId());
                        UserEntity byUser = userService.queryByInvitationCode(user.getInviterCode());
                        //记录邀请和计算邀请人收益
                        String format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
                        inviteService.updateInvite(byUser,format1,user.getUserId(),orders.getPayMoney());
                        //根据类型处理订单，会员业务和非会员业务
                        ordersService.insertOrders(orders);
                        //购买剧点单独处理
                        if (orders.getOrdersType().equals(4)) {
                            PayClassify payClassify = payClassifyService.getById(orders.getPayClassifyId());
                            if (ObjectUtils.isNotEmpty(payClassify)){
                                UserDramaPoint userDramaPoint = userDramaPointDao.selectOne(new LambdaQueryWrapper<UserDramaPoint>().eq(UserDramaPoint::getUserId, user.getUserId()));
                                if (ObjectUtils.isEmpty(userDramaPoint)){//支付成功后增加剧点余额
                                    userDramaPoint.setBalance(userDramaPoint.getBalance().add(new BigDecimal(payClassify.getGiveCoin())).add(new BigDecimal(payClassify.getCoin())));
                                    userDramaPointDao.updateById(userDramaPoint);
                                    //记录剧点详情
                                    UserDramaDetails dramaPointDetail = new UserDramaDetails();
                                    dramaPointDetail.setUserId(Math.toIntExact(user.getUserId()));
                                    dramaPointDetail.setOrdersId(Math.toIntExact(orders.getOrdersId()));
                                    dramaPointDetail.setTitle("购买剧点成功，订单号："+orders.getOrdersNo());
                                    dramaPointDetail.setType(1);
                                    dramaPointDetail.setAmount(new BigDecimal(payClassify.getGiveCoin()).add(new BigDecimal(payClassify.getCoin())));
                                    dramaPointDetail.setContent("增加剧点："+new BigDecimal(payClassify.getGiveCoin()).add(new BigDecimal(payClassify.getCoin()))+"点");
                                    dramaPointDetail.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                                    userDramaDetailsDao.insert(dramaPointDetail);

                                }
                            }
                        }
                        return Result.success();
                    }
                    return Result.error("当前交易不在交易列表中");
                }else {//IOS7之前
                    String transaction_id = returnJson.getString("transaction_id");
                    //交易列表包含当前交易，则认为交易成功
                    if (transaction_id.equals(iospayDto.getTransactionId())) {
                        //处理业务逻辑
                        Orders orders = ordersService.selectOrderById(iospayDto.getOrderId());
                        if (ObjectUtils.isEmpty(orders))return Result.error("该订单不存在");
                        orders.setStatus(OrdersConstants.ORDERS_STATUS_PAID);
                        orders.setPayWay(OrdersConstants.ORDERS_PAY_WAY_APPLE);
                        orders.setTransactionId(Long.valueOf(iospayDto.getTransactionId()));
                        ordersService.updateById(orders);
                        UserEntity user = userService.selectUserById(orders.getUserId());
                        UserEntity byUser = userService.queryByInvitationCode(user.getInviterCode());
                        //记录邀请和计算邀请人收益
                        String format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
                        inviteService.updateInvite(byUser,format1,user.getUserId(),orders.getPayMoney());
                        //根据类型处理订单，会员业务和非会员业务
                        ordersService.insertOrders(orders);
                        //购买剧点单独处理
                        if (orders.getOrdersType()==4){
                            PayClassify payClassify = payClassifyService.getById(orders.getPayClassifyId());
                            if (ObjectUtils.isNotEmpty(payClassify)){
                                //增加用户剧点余额
                                UserDramaPoint userDramaPoint = userDramaPointDao.selectById(orders.getUserId());
                                userDramaPoint.setBalance(new BigDecimal(payClassify.getCoin()).add(new BigDecimal(payClassify.getGiveCoin())));
                                userDramaPointDao.updateById(userDramaPoint);
                                //增加用户购买记录
                                UserDramaDetails userDramaDetails = new UserDramaDetails();
                                userDramaDetails.setUserId(orders.getUserId().intValue());
                                userDramaDetails.setContent("新增剧点:"+payClassify.getCoin()+payClassify.getGiveCoin()+"点");
                                userDramaDetails.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                                userDramaDetails.setTitle("剧点购买成功,订单号："+orders.getOrdersNo());
                                userDramaDetails.setType(1);
                                userDramaDetails.setAmount(new BigDecimal(payClassify.getCoin()).add(new BigDecimal(payClassify.getGiveCoin())));
                                userDramaDetails.setOrdersId(orders.getOrdersId().intValue());
                                userDramaDetailsDao.insert(userDramaDetails);
                            }

                        }
                        return Result.success();
                    }
                    return Result.error("未能获取到交易列表");
                }
            } else {
                return Result.error("支付失败，状态码：" + states);
            }
        }
    }


    /**
     * 苹果ios服务通知回调
     */
    @RequestMapping("/iosNotification")
    @Transactional
    public Result iosNotification(@RequestBody IosNotificationRequest request) throws CertificateException {
        log.info("Apple iOS 服务器通知进来, request:{}", JSONObject.toJSONString(request));
        String signedPayLoad = request.getSignedPayLoad();
        try {
            JSONObject payload = IosVerifyUtil.verifyAndGet(signedPayLoad);

            String notificationType = payload.get("notificationType").toString();

            JSONObject data = payload.getJSONObject("data");
            log.info("Apple iOS 服务器通知验证成功, payload:{}, data:{}", payload, data);
            String signedTransactionInfo = data.get("signedTransactionInfo").toString();
            String environment = data.get("environment").toString();

            JSONObject transactionInfo = IosVerifyUtil.verifyAndGet(signedTransactionInfo);
            String transactionId = transactionInfo.get("transactionId").toString();
            String originalTransactionId = transactionInfo.get("originalTransactionId").toString();
            String productId = transactionInfo.get("productId").toString();

            if ("DID_RENEW".equals(notificationType)) {
                // 处理订阅续期业务逻辑

            } else if ("REFUND".equals(notificationType)) {
                // 处理退款业务逻辑
                LambdaQueryWrapper<Orders> ordersLambdaQueryWrapper = new LambdaQueryWrapper<>();
                ordersLambdaQueryWrapper.eq(Orders::getTransactionId, transactionId);
                ordersLambdaQueryWrapper.eq(Orders::getPayWay,OrdersConstants.ORDERS_PAY_WAY_APPLE);
                ordersLambdaQueryWrapper.eq(Orders::getStatus,OrdersConstants.ORDERS_STATUS_PAID);
                Orders orders = ordersService.getOne(ordersLambdaQueryWrapper);
                //todo 记录未查询出的退款
                if (orders != null) {
                    orders.setStatus(OrdersConstants.ORDERS_STATUS_REFUND);
                    ordersService.updateById(orders);
                    //todo 退款成功后，更新用户会员信息
                    if (orders.getOrdersType() == 1) {
                        LambdaQueryWrapper<CourseUser> courseUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
                        courseUserLambdaQueryWrapper.eq(CourseUser::getOrderId, orders.getOrdersId());
                        CourseUser courseUser = courseUserService.getOne(courseUserLambdaQueryWrapper);
                        if (courseUser != null) {
                            //删除courseUser
                            courseUserService.removeById(courseUser.getCourseUserId());
                        }
                    } else if (orders.getOrdersType() == 2) {
                        UserVip userVip = userVipService.selectUserVipByUserId(orders.getUserId());
                        if (userVip != null) {
                            userVipService.removeById(userVip.getVipId());
                        }
                        LambdaQueryWrapper<Orders> ordersLambdaQueryWrapper1 = new LambdaQueryWrapper<>();
                        ordersLambdaQueryWrapper1.eq(Orders::getUserId, orders.getUserId());
                        ordersLambdaQueryWrapper1.eq(Orders::getPayWay, OrdersConstants.ORDERS_PAY_WAY_FREE);
                        ordersLambdaQueryWrapper1.eq(Orders::getStatus, OrdersConstants.ORDERS_STATUS_PAID);
                        List<Orders> ordersList = ordersService.list(ordersLambdaQueryWrapper1);
                        if (ordersList != null && ordersList.size() > 0) {
                            List<Long> list = ordersList.stream().map(Orders::getOrdersId).collect(Collectors.toList());
                            courseUserService.removeByIds(list);
                        }
                    }//苹果充值到app的余额一般不允许退款
                }

            } else {
                log.error("notificationType:{}未处理", notificationType);
            }

        } catch (CertificateException e) {
            log.error("Apple iOS 服务器通知验证错误, signedPayLoad:{}", signedPayLoad, e);
            Result.success();
        }
        return Result.success();
    }



    /**
     * 获取Braintree的token，Braintree公司的三方支付
     * @return
     */
    @GetMapping("/getToken")
    public Result getToken(){
        BraintreeGateway gateway = new BraintreeGateway(
                Environment.SANDBOX,
                "pdqgy89nz6nccvhg",
                "sf5qsdy3fj69gx92",
                "a75baeca471b7d52e9409e9c818166d9"
        );
        String clientToken = gateway.clientToken().generate();
        return Result.success().put("token",clientToken);
    }

    @PostMapping("/iosPay")
    @Transactional
    public Result applePay(@RequestBody ApplePayDto applePayDto) throws Exception {
//        PrivateKey privateKey = readPrivateKeyFromFile("D:\\工作\\九州影视\\jiuzhouyingshi\\ss\\apple_pay.cer");
//        PublicKey publicKey = readPublicKeyFromFile("D:\\工作\\九州影视\\jiuzhouyingshi\\ss\\merchant_id.cer");
//        // 设置 Braintree 的环境和密钥
//        BraintreeGateway gateway = new BraintreeGateway(
//                Environment.SANDBOX,
//                "merchant.app.QiWang.com",
//                privateKey.toString(),
//                publicKey.toString()
//        );
        //D:\JAVA\idea2022\ss\apple_pay.cer
        //D:\JAVA\idea2022\ss\merchant_id.cer
        //Braintree沙盒环境
        BraintreeGateway gateway = new BraintreeGateway(
                Environment.SANDBOX,
                "pdqgy89nz6nccvhg",
                "sf5qsdy3fj69gx92",
                "a75baeca471b7d52e9409e9c818166d9"
        );


        try {
            // 创建交易请求
            TransactionRequest request = new TransactionRequest()
                    .amount(applePayDto.getMoney())
                    .paymentMethodNonce(applePayDto.getPaymentMethodNonce())
                    .type(Transaction.Type.SALE);

            // 发起交易
            com.braintreegateway.Result<Transaction> result = gateway.transaction().sale(request);

            if (result.isSuccess()) {
                Transaction transaction = result.getTarget();
                Orders orders = ordersService.selectOrderById(applePayDto.getOrderId().longValue());
                orders.setTransactionId(Long.valueOf(transaction.getId()));
                orders.setStatus(OrdersConstants.ORDERS_STATUS_PAID);
                System.out.println("支付成功：交易 ID = " + transaction.getId());
                return Result.success();
            } else {
                System.out.println("支付失败：" + result.getMessage());
            }
        } catch (Exception e) {
            System.out.println("发生错误：" + e.getMessage());
        }
        return Result.success();
    }

    public static String privateKeyToString(PrivateKey privateKey) throws Exception {
        byte[] encodedPrivateKey = privateKey.getEncoded();
        return Base64.getEncoder().encodeToString(encodedPrivateKey);
    }

    public static String publicKeyToString(PublicKey publicKey) throws Exception {
        byte[] encodedPublicKey = publicKey.getEncoded();
        return Base64.getEncoder().encodeToString(encodedPublicKey);
    }

    public static PublicKey readPublicKeyFromFile(String filePath) throws Exception {
        FileInputStream fis = new FileInputStream(filePath);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        X509Certificate certificate = (X509Certificate) cf.generateCertificate(fis);
        fis.close();
        return certificate.getPublicKey();
    }

    public static PrivateKey readPrivateKeyFromFile(String filePath) throws Exception {
        FileInputStream fis = new FileInputStream(filePath);
        byte[] keyBytes = new byte[fis.available()];
        fis.read(keyBytes);
        fis.close();

        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePrivate(spec);
    }


    /**
     *
     * @param transactionId 苹果生成的订单id
     * @param payload 账单
     * @return
     */
    public Result iosPay1(String transactionId, String payload){
        //1.先线上测试    发送平台验证
        String verifyResult = IosVerifyUtil.buyAppVerify(payload, 1);
        //苹果服务器没有返回验证结果
        if (verifyResult == null) {
            log.info("无订单信息!");
            Result.error("无订单信息");
        }
        // 苹果验证有返回结果
        log.info("线上，苹果平台返回JSON:" + verifyResult);
        JSON job = JSONUtil.parse(verifyResult);
        String states = job.getByPath("status").toString();
        //0 正常
        //21000 App Store不能读取你提供的JSON对象
        //21002 receipt-data域的数据有问题
        //21003 receipt无法通过验证
        //21004 提供的shared secret不匹配你账号中的shared secret
        //21005 receipt服务器当前不可用
        //21006 receipt合法，但是订阅已过期。服务器接收到这个状态码时，receipt数据仍然会解码并一起发送
        //21007 receipt是Sandbox receipt，但却发送至生产系统的验证服务
        //21008 receipt是生产receipt，但却发送至Sandbox环境的验证服务
        if ("21007".equals(states)) { //是沙盒环境，应沙盒测试，否则执行下面
            //2.再沙盒测试  发送平台验证
            verifyResult = IosVerifyUtil.buyAppVerify(payload, 0);
            log.info("沙盒环境，苹果平台返回JSON:" + verifyResult);
            job = JSONUtil.parse(verifyResult);
            states = job.getByPath("status").toString();
        }
        log.info("苹果平台返回值：job" + job);
        if (states.equals("0")) { // 前端所提供的收据是有效的    验证成功
            JSON inAppJson = JSONUtil.parse(JSONUtil.getByPath(job, "receipt.in_app"));
            List<JSON> jsons = JSONUtil.toList(inAppJson.toString(), JSON.class);
            //所有支付成功的订单号
            List<String> transaction_id =
                    jsons.stream().map(t -> t.getByPath("transaction_id").toString())
                            .distinct().collect(Collectors.toList());
            if(transaction_id.contains(transactionId)){
                log.info("苹果正式环境会员开通成功，内购商品id为:{}", transactionId);
                return Result.success();
            }
            return Result.error();
        } else {
            return Result.error("receipt数据有问题");
        }

    }
}
